#include<bits/stdc++.h>
#define N 110000
#define eps 1e-7
#define inf 1e9+7
#define db double
#define ll long long
#define ldb long double
#define ull unsigned long long
using namespace std;
inline int read()
{
	char ch=0;
	int x=0,flag=1;
	while(!isdigit(ch)){ch=getchar();if(ch=='-')flag=-1;}
	while(isdigit(ch)){x=(x<<3)+(x<<1)+ch-'0',ch=getchar();}
	return x*flag;
}
#define lson son[x][0]
#define rson son[x][1]
int f[N],v[N],st[N],sumv[N],flag[N],son[N][2];
void pushup(int x){sumv[x]=sumv[lson]^sumv[rson]^v[x];}
void update(int x){flag[x]^=1;swap(lson,rson);}
bool get(int x){return son[f[x]][1]==x;}
bool isrt(int x){return x!=son[f[x]][0]&&x!=son[f[x]][1];}
void pushdown(int x)
{
	if(!flag[x])return;
	if(lson)update(lson);
	if(rson)update(rson);
	flag[x]=0;
}
void rotate(int x)
{
	int y=f[x],z=f[y],tx=get(x),ty=get(y),p=son[x][!tx];
	if(!isrt(y))son[z][ty]=x;son[x][!tx]=y;son[y][tx]=p;
	if(p)f[p]=y;f[x]=z;f[y]=x;pushup(y);pushup(x);
}
void splay(int x)
{
	int t=x,cnt=0;
	while(!isrt(x))st[++cnt]=x,x=f[x];
	st[++cnt]=x;x=t;
	for(int i=cnt;i>=1;i--)pushdown(st[i]);
	while(!isrt(x))
	{
		int y=f[x];
		if(!isrt(y))rotate(get(x)==get(y)?y:x);
		rotate(x);
	}
}
void access(int x){for(int y=0;x;y=x,x=f[x])splay(x),son[x][1]=y,pushup(x);}
void makeroot(int x){access(x);splay(x);update(x);}
int findroot(int x)
{
	access(x);splay(x);
	while(son[x][0])pushdown(x),x=son[x][0];
	splay(x);return x;
}
void split(int x,int y){makeroot(x);access(y);splay(y);}
void link(int x,int y){makeroot(x);if(findroot(y)!=x)f[x]=y;}
void cut(int x,int y)
{
	split(x,y);
	if(son[y][0]!=x||son[x][1])return;
	f[x]=son[y][0]=0;pushup(y);
}
int query(int x,int y){split(x,y);return sumv[y];}
int main()
{
	int n=read(),m=read();
	for(int i=1;i<=n;i++)v[i]=read();
	for(int i=1;i<=m;i++)
	{
		int opt=read(),x=read(),y=read();
		if(opt==0)printf("%d\n",query(x,y));
		if(opt==1)link(x,y);
		if(opt==2)cut(x,y);
		if(opt==3){splay(x);v[x]=y;pushup(x);}
	}
	return 0;
}
